﻿using System;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Steer
{
    public class Vector2D
    {
        private double _x;
        private double _y;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public Vector2D(double x, double y)
        {
            _x = x;
            _y = y;
        }

        public double x
        {
            get
            {
                return _x;
            }
            set
            {
                _x = value;
            }
        }

        public double y
        {
            get
            {
                return _y;
            }
            set
            {
                _y = value;
            }
        }

        /// <summary>
        /// 克隆
        /// </summary>
        /// <returns></returns>
        public Vector2D clone()
        {
            return new Vector2D(x, y);
        }

        /// <summary>
        /// 初始化向量
        /// </summary>
        /// <returns></returns>
        public Vector2D zero()
        {
            _x = 0;
            _y = 0;
            return this;
        }

        /// <summary>
        /// 这个向量是否等于零,即x,y,长度为零。
        /// </summary>
        /// <returns></returns>
        public bool isZero()
        {
            return _x == 0 && _y == 0;
        }

        /// <summary>
        /// 向量大小
        /// </summary>
        public double length
        {
            get
            {
                return Math.Sqrt(lengthSQ);
            }
            set
            {
                double a = angle;
                _x = Math.Cos(a) * value;
                _y = Math.Sin(a) * value;
            }
        }
        /// <summary>
        /// 得到这个向量长度的平方。
        /// </summary>
        public double lengthSQ
        {
            get
            {
                return _x * _x + _y * _y;
            }
        }

        /// <summary>
        /// 得到这个向量角度。
        /// </summary>
        public double angle
        {
            get
            {
                return Math.Atan2(_y, _x);
            }
            set
            {
                double len = length;
                _x = Math.Cos(value) * len;
                _y = Math.Sin(value) * len;
            }
        }

        /// <summary>
        /// 单位化向量，设定长度为一,更有效率。
        /// </summary>
        /// <returns></returns>
        public Vector2D normalize()
        {
            if (length == 0)
            {
                _x = 1;
                return this;
            }
            double len = length;
            _x/=len;
            _y/=len;
            return this;
        }

        /// <summary>
        /// 截断
        /// </summary>
        /// <param name="max"></param>
        /// <returns></returns>
        public Vector2D truncate(double max)
        {
            length = Math.Min(max, length);
            return this;
        }

        /// <summary>
        /// 倒置
        /// </summary>
        /// <returns></returns>     
        public Vector2D reverse()
        {
            _x = -_x;
            _y = -_y;
            return this;
        }

        /// <summary>
        /// 是否单位化
        /// </summary>
        /// <returns></returns>
        public bool isNormalized()
        {
            return length == 1.0;
        }

        /// <summary>
        /// 积
        /// </summary>
        /// <param name="v2"></param>
        /// <returns></returns>
        public double dotProd(Vector2D v2)
        {
            return _x * v2.x + _y * v2.y;
        }

        /// <summary>
        /// 差
        /// </summary>
        /// <param name="v2"></param>
        /// <returns></returns>
        public double crossProd(Vector2D v2) {
            return _x * v2.y - _y * v2.x;
        }

        /// <summary>
        /// 两个向量之差
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <returns></returns>
        public static double angleBetween(Vector2D v1, Vector2D v2)
        {
            if (!v1.isNormalized())
            {
                v1 = v1.clone().normalize();
            }
            if (v2.isNormalized())
            {
                v2 = v2.clone().normalize();
            }
            return Math.Acos(v1.dotProd(v2));
        }

        /// <summary>
        /// 确定给定向量的方向
        /// </summary>
        /// <param name="v2"></param>
        /// <returns></returns>
        public int sign(Vector2D v2)
        {
            return perp.dotProd(v2) < 0 ?-1: 1;
        }

        /// <summary>
        /// 垂直与这个向量的向量
        /// </summary>
        public Vector2D perp
        {
            get
            {
                return new Vector2D(-y, x);
            }
        }

        /// <summary>
        /// 两个向量间的距离
        /// </summary>
        /// <param name="v2"></param>
        /// <returns></returns>
        public double dist(Vector2D v2)
        {
            return Math.Sqrt(distSQ(v2));
        }

        /// <summary>
        /// 计算向量到另一个给定向量的距离
        /// </summary>
        /// <param name="v2"></param>
        /// <returns></returns>
        public double distSQ(Vector2D v2)
        {
            double dx = v2.x - x;
            double dy = v2.y - y;
            return dx * dx + dy * dy;
        }

        /// <summary>
        /// 和
        /// </summary>
        /// <param name="v2"></param>
        /// <returns></returns>
        public Vector2D add(Vector2D v2)
        {
            return new Vector2D(_x + v2.x, _y + v2.y);
        }

        /// <summary>
        /// 差
        /// </summary>
        /// <param name="v2"></param>
        /// <returns></returns>
        public Vector2D subtract(Vector2D v2)
        {
            return new Vector2D(_x - v2.x, _y - v2.y);
        }

        /// <summary>
        /// 翻倍
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public Vector2D multiply(double value)
        {
            return new Vector2D(_x * value, _y * value);
        }

        /// <summary>
        /// 减倍
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public Vector2D divide(double value)
        {
            return new Vector2D(_x / value, _y / value);
        }

        /// <summary>
        /// 是否相等
        /// </summary>
        /// <param name="v2"></param>
        /// <returns></returns>
        public bool equals(Vector2D v2)
        {
            return _x == v2.x && _y == v2.y;
        }

        public override string ToString()
        {
            return "[Vector2D(x:" + _x + ",y:" + _y + ")]";
        }
    }
}
